package com.baibei.ebec.sdk;

import com.baibei.sdk.ResponseConverter;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonResponseBodyConverter;
import retrofit2.converter.gson.IGsonResponseBodyConverter;

/**
 * Created by ChenRui on 2017/8/8 0008 11:58.
 */
public class ApiConverterFactory extends Converter.Factory {
    /**
     * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
     * decoding from JSON (when no charset is specified by a header) will use UTF-8.
     */
    public static ApiConverterFactory create() {
        return create(new Gson());
    }

    /**
     * Create an instance using {@code gson} for conversion. Encoding to JSON and
     * decoding from JSON (when no charset is specified by a header) will use UTF-8.
     */
    public static ApiConverterFactory create(Gson gson) {
        return new ApiConverterFactory(gson);
    }

    public static ApiConverterFactory create(Gson gson, IGsonResponseBodyConverter converter) {
        return new ApiConverterFactory(gson, converter);
    }

    public static ApiConverterFactory create(IGsonResponseBodyConverter converter) {
        return new ApiConverterFactory(new Gson(), converter);
    }

    private final Gson gson;
    private IGsonResponseBodyConverter mResponseBodyConverter;

    private ApiConverterFactory(Gson gson) {
        this(gson, new IGsonResponseBodyConverter() {
            @Override
            public Converter<ResponseBody, ?> responseBodyConverter(Gson gson, TypeAdapter<?> adapter, Type type, Annotation[] annotations) {
                return new ResponseConverter<>(gson, adapter, type, annotations);
            }
        });
    }


    private ApiConverterFactory(Gson gson, IGsonResponseBodyConverter converter) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
        mResponseBodyConverter = converter;
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));

        if (mResponseBodyConverter != null) {
            return mResponseBodyConverter.responseBodyConverter(gson, adapter, type, annotations);
        } else {
            return new GsonResponseBodyConverter<>(gson, adapter, type, annotations);
        }
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new ApiRequestBodyConverter<>(gson, adapter);
    }
}
